package multi_thread.train;

import multi_thread.master.executors.ForkJoinExample;

import java.util.concurrent.ExecutionException;
import java.util.stream.LongStream;

/**
 * @author Cheng Jun
 * Description: 1~ 1_000_000_000 大数字求和(自然数)
 * @version 1.0
 * @date 2022/5/22 22:15
 */
public class BigNumberSum {

    public static void main(String[] args) {
        long begin = 0L;
        long end = 1_000_000_000L;
        // 耗时 0ms 或 1ms
        mathSum(begin, end);

        // 耗时 400~500ms
        streamSum(begin, end);

        // 耗时 300~400ms
        forSum(begin, end);

        // 耗时 400~500ms 数字变大，对耗时影响不大，且结果更不容易出错
        forJoinSum(begin, end);
    }

    // 利用数学的求和公式
    private static void mathSum(long begin, long end) {
        long startMilli = System.currentTimeMillis();
        if (((end + begin) & 1) == 1) {
            System.out.println(((end - begin + 1) / 2) * (end + begin));
        }else {
            System.out.println(((end + begin) / 2) * (end - begin + 1));
        }
        long endMilli = System.currentTimeMillis();
        System.out.println("endMilli - startMilli = " + (endMilli - startMilli));
    }

    // 流式的并行计算效率 和 机器的CPU核数成正相关
    private static void streamSum(long begin, long end) {
        long startMilli = System.currentTimeMillis();
        System.out.println(LongStream.rangeClosed(begin, end).parallel().sum());
        long endMilli = System.currentTimeMillis();
        System.out.println("endMilli - startMilli = " + (endMilli - startMilli));
    }

    private static void forSum(long begin, long end) {
        long startMilli = System.currentTimeMillis();
        long sum = 0;
        for (long i = begin; i <= end; i++) {
            sum += i;
        }
        System.out.println(sum);
        long endMilli = System.currentTimeMillis();
        System.out.println("endMilli - startMilli = " + (endMilli - startMilli));
    }


    private static void forJoinSum(long begin, long end) {
        try {
            ForkJoinExample.main(new String[0]);
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
